/*
 * Copyright 2019 成都深地领航能源科技有限公司. All rights reserved.
 * PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package com.sdlh.demo.encrypt;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

/**
 * @author 成都深地领航能源科技有限公司
 */
public class EncryptedUtils {

    private static final String ALGORITHM = "AES";
    private static final String TRANSFORMATION = "AES";
    private static final String SECRET_KEY = "my-long-encryption-key-123456121"; // 替换为你自己的密钥


    /**
     * 文件加密
     * @param inputFile  文件路径
     * @param encryptedFile 加密后文件路径
     */
    public static void encryptFile(String inputFile, String encryptedFile) {
        doCrypto(Cipher.ENCRYPT_MODE, inputFile, encryptedFile);
    }

    /**
     * 文件解密
     * @param encryptedFile 加密文件路径
     * @param decryptedFile 解密文件路径
     */
    public static void decryptFile(String encryptedFile, String decryptedFile) {
        doCrypto(Cipher.DECRYPT_MODE, encryptedFile, decryptedFile);
    }

    /**
     * 加密文件处理并输出
     * @param cipherMode
     * @param inputFile
     * @param outputFile
     */
    private static void doCrypto(int cipherMode, String inputFile, String outputFile) {
        try(FileInputStream inputStream = new FileInputStream(inputFile);
            FileOutputStream outputStream = new FileOutputStream(outputFile);) {
            SecretKey secretKey = new SecretKeySpec(SECRET_KEY.getBytes(), ALGORITHM);
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            cipher.init(cipherMode, secretKey);
            byte[] buffer = new byte[1024];
            int bytesRead;

            while ((bytesRead = inputStream.read(buffer)) != -1) {
                byte[] outputBytes = cipher.update(buffer, 0, bytesRead);

                if (outputBytes != null) {
                    outputStream.write(outputBytes);
                }
            }
            byte[] outputBytes = cipher.doFinal();

            if (outputBytes != null) {
                outputStream.write(outputBytes);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 返回加密字节
     * @return
     * @throws NoSuchAlgorithmException
     * @throws NoSuchPaddingException
     * @throws InvalidKeyException
     * @throws IllegalBlockSizeException
     * @throws BadPaddingException
     */
    public static byte[] encrypt(String content) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
        SecretKey secretKey = new SecretKeySpec(SECRET_KEY.getBytes(), ALGORITHM);
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        byte[] contentBytes = content.getBytes("utf-8");
        int len = contentBytes.length;
        // 计算需要填充的长度
                int padLen = 16 - (len % 16);
        // 构造新的字节数组，长度为原字节数组加上需要填充的长度
                byte[] paddedBytes = new byte[len + padLen];
        // 复制原字节数组到新字节数组中
                System.arraycopy(contentBytes, 0, paddedBytes, 0, len);
        // 对新字节数组进行填充
        for (int i = len; i < len + padLen; i++) {
            paddedBytes[i] = (byte) padLen;
        }
        byte[] encryptedBytes = cipher.doFinal(content.getBytes());
        return encryptedBytes;
    }
    public static byte[] encryptAndWriteToFile(String plaintext) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, IllegalBlockSizeException, BadPaddingException {
        SecretKey secretKey = new SecretKeySpec(SECRET_KEY.getBytes(), ALGORITHM);
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);

            byte[] plaintextBytes = plaintext.getBytes("utf-8");
            int blockSize = cipher.getBlockSize();
            int paddedLength = (int) Math.ceil((double) plaintextBytes.length / blockSize) * blockSize;
            byte[] paddedBytes = new byte[paddedLength];
            System.arraycopy(plaintextBytes, 0, paddedBytes, 0, plaintextBytes.length);
           // cipherOutputStream.write(paddedBytes);
            return paddedBytes;

    }
    /**
     * 将字符串加密后写到文件夹
     * @param plainText
     * @param filePath
     * @throws NoSuchAlgorithmException
     * @throws NoSuchPaddingException
     * @throws InvalidKeyException
     * @throws IOException
     * @throws IllegalBlockSizeException
     * @throws BadPaddingException
     */
    public static void encryptStringToFile(String plainText, String filePath) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, IllegalBlockSizeException, BadPaddingException {
        SecretKey secretKey = new SecretKeySpec(SECRET_KEY.getBytes(), ALGORITHM);
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);

        byte[] encryptedBytes = cipher.doFinal(plainText.getBytes());
        String encryptedString = Base64.getEncoder().encodeToString(encryptedBytes);

        try (FileWriter fileWriter = new FileWriter(filePath);
             BufferedWriter bufferedWriter = new BufferedWriter(fileWriter)) {

            bufferedWriter.write(encryptedString);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //对文件夹解密
    public static String decryptFileToString(String filePath) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, IllegalBlockSizeException, BadPaddingException {
        SecretKey secretKey = new SecretKeySpec(SECRET_KEY.getBytes(), ALGORITHM);
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.DECRYPT_MODE, secretKey);

        String encryptedString;

        try (FileReader fileReader = new FileReader(filePath);
             BufferedReader bufferedReader = new BufferedReader(fileReader)) {

            encryptedString = bufferedReader.readLine();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }

        byte[] encryptedBytes = Base64.getDecoder().decode(encryptedString);
        byte[] decryptedBytes = cipher.doFinal(encryptedBytes);

        return new String(decryptedBytes);
    }

    /**
     * 写文件到指定地方
     * @param text
     * @param filePath
     * @throws IOException
     */
    public static void writeStringToFile(String text, String filePath) throws IOException {
        try (FileWriter fileWriter = new FileWriter(filePath);
             BufferedWriter bufferedWriter = new BufferedWriter(fileWriter)) {

            bufferedWriter.write(text);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 对数组加解密
     * @param bytes
     * @return
     */
    public  static byte[] deal(byte[] bytes)  {

        for (int i = 0; i < bytes.length; i++) {
            bytes[i] = (byte) (bytes[i] ^ 9527);
        }

        return bytes;
    }

}
